package com.plian.system.service.fr.audit.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.spring.SpringUtil;
import com.plian.system.bean.wtzg.RectificationSituationExcelBean;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dao.sys.orgzation.OrgzationDao;
import com.plian.system.entity.fr.audit.AuditOrganizations;
import com.plian.system.entity.ms.RectificationSituation;
import com.plian.system.mapper.fr.audit.AuditOrganizationsMapper;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.properties.GzwProperties;
import com.plian.system.service.fr.audit.IAuditOrganizationsService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.fr.audit.AuditOrganizationsVO;
import com.plian.system.wrapper.fr.audit.AuditOrganizationsWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.util.*;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 内部机构管理 服务实现类
 *
 * @author gangan
 * @since 2019-10-09
 */
@Slf4j
@Service
@AllArgsConstructor
public class AuditOrganizationsServiceImpl extends BaseServiceImpl<AuditOrganizationsMapper, AuditOrganizations> implements IAuditOrganizationsService, BaseFlowService {

    private final OrgzationDao orgzationDao;

    private final FormWorkflowService formWorkflowService;

    private final IFormCodeService formCodeService;

    private final AuditOrganizationsWrapper auditOrganizationsWrapper;
    private final AuditOrganizationsMapper auditOrganizationsMapper;
    private Environment environment;
    private OrgzationService orgzationService;
    private static Map<String, String> fileNameMap = new HashMap<>();
    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean saveOrUpdate(AuditOrganizations auditOrganizations) {
        if (auditOrganizations.getId() == null){
            auditOrganizations.setCode(formCodeService.getCode(FormTypeConstant.FR_AUDITORGANIZATIONS_FORM));
            auditOrganizations.setFormType(String.valueOf(FormTypeConstant.FR_AUDITORGANIZATIONS_FORM));
        }
        boolean result = super.saveOrUpdate(auditOrganizations);
        if (auditOrganizations.getStatus() == FormStatusConstant.UNREVIEWED){
            HashMap<String, Object> processVariable = new HashMap<>();
            formWorkflowService.startProcessAndSimulate(String.valueOf(auditOrganizations.getId()),auditOrganizations.getFormType(),processVariable);
        }

        return result;
    }

    @Override
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            AuditOrganizations auditOrganizations = getById(id);
            if (auditOrganizations == null) {
                return false;
            } else if (auditOrganizations.getStatus() != null &&
                    (auditOrganizations.getStatus() != FormStatusConstant.STASH && auditOrganizations.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }
        return super.deleteLogic(ids);
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        /**
         * 设置审批人和审批时间
         */
        AuditOrganizations auditOrganizations = getById(id);
        auditOrganizations.setApprovedUser(TokenUtil.getTokenUserId());
        Date now = DateUtil.now();
        auditOrganizations.setApprovedTime(now);
        updateById(auditOrganizations);
        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState);
    }

    @Override
    public Boolean checkIsExisted(Long id, String code , String companyId) {

        if (StringUtil.isNotBlank(code)) {
            AuditOrganizations auditOrganizations = new AuditOrganizations();
            auditOrganizations.setCode(code);
            if (Optional.ofNullable(getOne(Condition.getQueryWrapper(auditOrganizations))).isPresent()) {
                if (id==null || !id.equals(getOne(Condition.getQueryWrapper(auditOrganizations)).getId())){
                    return false;
                }
            }
        }
        if (StringUtil.isNotBlank(companyId)) {
            List<AuditOrganizations> list = list(Condition.getQueryWrapper(new AuditOrganizations())
                    .lambda().eq(AuditOrganizations::getCompanyNameId, companyId));
            if (list.size()>0 ) {
                return id != null && id.equals(list.get(0).getId());
            }
        }
        return true;
    }

//    @Override
//    public ReportReturnVO auditAgencyBasic(AuditOrganizationsDTO auditOrganizationsDTO) throws Exception{
//        LambdaQueryWrapper<AuditOrganizations> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(AuditOrganizations::getStatus,3);
//        if (Optional.ofNullable(auditOrganizationsDTO).isPresent()){
//            if (CollectionUtil.isNotEmpty(auditOrganizationsDTO.getCompanyNameIds())){
//               queryWrapper.in(AuditOrganizations::getCompanyNameId, auditOrganizationsDTO.getCompanyNameIds());
//            }
//            if (Optional.ofNullable(auditOrganizationsDTO.getInstitutionName()).isPresent()){
//                queryWrapper.like(AuditOrganizations::getInstitutionName, auditOrganizationsDTO.getInstitutionName());
//            }
//            if (Optional.ofNullable(auditOrganizationsDTO.getPrincipal()).isPresent()){
//                queryWrapper.like(AuditOrganizations::getPrincipal, auditOrganizationsDTO.getPrincipal());
//            }
//        }
//
//        List<AuditOrganizations> auditOrganizationsList = list(queryWrapper);
//
//        List<AuditOrganizationsVO> data = new ArrayList<>();
//        if (CollectionUtil.isNotEmpty(auditOrganizationsList)){
//            List<AuditOrganizationsVO> auditOrganizationsVOS = auditOrganizationsWrapper.entityToVO(auditOrganizationsList);
////            if (Optional.ofNullable(auditOrganizationsVOS.getDef1()).isPresent()){
////                for(int i=auditOrganizationsVOS.size()-1; i>=0; i--){
////                    if(auditOrganizationsVOS.get(i).getPrincipalName()==null || !auditOrganizationsVOS.get(i).getPrincipalName().contains(auditOrganizationsVOS.getDef1())){
////                        auditOrganizationsVOS.remove(i);
////                    }
////                }
////            }
//            int sum = 0;
//            List<PageData> allOrgs =  orgzationDao.list(null);
//            Map<String, List<AuditOrganizationsVO>> map = auditOrganizationsVOS.stream().collect(Collectors.groupingBy(AuditOrganizationsVO::getCompanyNameId));
//
//            for (PageData org : allOrgs){
//                if (map.containsKey(org.get("id"))){
//                    data.addAll(map.get(org.get("id")));
//
//                    sum += map.get(org.get("id")).size();
//                    AuditOrganizationsVO vo = new AuditOrganizationsVO();
//                    vo.setCompanyName("小计：" + map.get(org.get("id")).size());
//                    vo.setTotalPeople(map.get(org.get("id")).stream().filter(auditOrganizationsVO -> auditOrganizationsVO.getTotalPeople() != null)
//                            .mapToInt(AuditOrganizationsVO::getTotalPeople).sum());
//                    vo.setFullInternalNum(map.get(org.get("id")).stream().filter(auditOrganizationsVO -> auditOrganizationsVO.getFullInternalNum() != null)
//                            .mapToInt(AuditOrganizationsVO::getFullInternalNum).sum());
//                    vo.setHoldingSubsidiary(map.get(org.get("id")).stream().mapToInt(AuditOrganizationsVO::getHoldingSubsidiary).sum());
//                    vo.setTotalAssets(map.get(org.get("id")).stream().filter(auditOrganizationsVO -> auditOrganizationsVO.getTotalAssets() != null)
//                            .map(AuditOrganizationsVO::getTotalAssets).reduce(BigDecimal.ZERO, BigDecimal::add));
//                    vo.setTotalLiabilities(map.get(org.get("id")).stream().filter(auditOrganizationsVO -> auditOrganizationsVO.getTotalLiabilities() != null)
//                            .map(AuditOrganizationsVO::getTotalLiabilities).reduce(BigDecimal.ZERO, BigDecimal::add));
//                    data.add(vo);
//                }
//            }
//
//            AuditOrganizationsVO end = new AuditOrganizationsVO();
//            end.setCompanyName("总计：" + sum);
//            end.setTotalPeople(data.stream().filter(auditOrganizationsVO -> "小计".equals(auditOrganizationsVO.getCompanyName()))
//                    .mapToInt(AuditOrganizationsVO::getTotalPeople).sum());
//            end.setFullInternalNum(data.stream().filter(auditOrganizationsVO -> "小计".equals(auditOrganizationsVO.getCompanyName()))
//                    .mapToInt(AuditOrganizationsVO::getFullInternalNum).sum());
//            end.setHoldingSubsidiary(data.stream().filter(auditOrganizationsVO -> "小计".equals(auditOrganizationsVO.getCompanyName()))
//                    .mapToInt(AuditOrganizationsVO::getHoldingSubsidiary).sum());
//            end.setTotalAssets(data.stream().filter(auditOrganizationsVO -> "小计".equals(auditOrganizationsVO.getCompanyName()))
//                    .map(AuditOrganizationsVO::getTotalAssets).reduce(BigDecimal.ZERO, BigDecimal::add));
//            end.setTotalLiabilities(data.stream().filter(auditOrganizationsVO -> "小计".equals(auditOrganizationsVO.getCompanyName()))
//                    .map(AuditOrganizationsVO::getTotalLiabilities).reduce(BigDecimal.ZERO, BigDecimal::add));
//            data.add(end);
//        }
//
//        ReportReturnVO reportReturnVO = new ReportReturnVO();
//        ReportVO reportVO = new ReportVO();
//
//        reportVO
//                .addHeader(HeaderVO.builder().key("companyName").title("企业名称").build())
//                .addHeader(HeaderVO.builder().key("institutionName").title("机构名称").build())
//                .addHeader(HeaderVO.builder().key("principalName").title("负责人").build())
//                .addHeader(HeaderVO.builder().key("totalPeople").title("总人数").build())
//                .addHeader(HeaderVO.builder().key("fullInternalNum").title("其中：专职内审人数").build())
//                .addHeader(HeaderVO.builder().key("holdingSubsidiary").title("控股子公司（个）").build())
//                .addHeader(HeaderVO.builder().key("totalAssets").title("资产总额（万元）").build())
//                .addHeader(HeaderVO.builder().key("totalLiabilities").title("负债总额（万元）").build());
//        reportVO.setData(data);
//        reportReturnVO.setGrids(reportVO);
//        return reportReturnVO;
//    }

    @Override
    public Boolean change(AuditOrganizations auditOrganizations) {
        auditOrganizations.setVersion(StringUtil.isBlank(auditOrganizations.getVersion()) ?
                "1" : String.valueOf(Integer.valueOf(auditOrganizations.getVersion())+1));
        return saveOrUpdate(auditOrganizations);
    }

    /**
     * 统一处理状态机事件方法
     * @param id 主键
     * @param updateStatus 更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            AuditOrganizations auditOrganizations = getById(id);
            auditOrganizations.setStatus(updateStatus);
            updateById(auditOrganizations);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        List<AuditOrganizations> auditOrganizations = list(new LambdaQueryWrapper<AuditOrganizations>().in(AuditOrganizations::getId,Func.toLongList(StringUtils.join(formIds, StringPool.COMMA))));
        List<AuditOrganizationsVO> auditOrganizationsVOS =auditOrganizationsWrapper.entityToVO(auditOrganizations);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(auditOrganizationsVOS)){
                for (AuditOrganizationsVO vo : auditOrganizationsVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getCompanyName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getCompanyNameId());
                    pd.put("formType", FormTypeConstant.FR_AUDITORGANIZATIONS_FORM);
                    pd.put("orgName", vo.getCompanyName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Collections.singletonList(FormTypeConstant.FR_AUDITORGANIZATIONS_FORM);
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }
    @Override
    public String export(){
        String key = System.currentTimeMillis() + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
        String fileName = key + ".xlsx";
        String exportPath = environment.getProperty("excel.path");
        /**
         * 导出路径不存在则创建
         */
        File file = new File(exportPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/auditOrganizationsExport.xlsx");
        ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

        WriteSheet staffFilesWriteSheet = EasyExcel.writerSheet(0).build();
        QueryWrapper<AuditOrganizations> queryWrapper = new QueryWrapper<>();
        this.addTokenQueryAudit(queryWrapper);
        List<AuditOrganizations> auditOrganizations=auditOrganizationsMapper.selectList(queryWrapper);
        List<AuditOrganizationsVO> auditOrganizationsVOS = auditOrganizationsWrapper.entityToVO(auditOrganizations);
        excelWriter.fill(auditOrganizationsVOS, fillConfig, staffFilesWriteSheet);
        excelWriter.finish();
        PageData org = orgzationService.getCompanyNameById(TokenUtil.getTokenOrgId());
        String companyName = "";
        if (org != null) {
            companyName = org.getString("name");
        }
        String excelName = companyName + "_内审机构管理";
        fileNameMap.put(key, excelName);
        return key;
    }
    /**
     * 根据flag 判断是否过滤登录信息 1本级所有数据和下级通过审批数据 2本级所有数据
     *
     * @param wrapper
     * @param
     * @return
     */
    public void addTokenQueryAudit(QueryWrapper<AuditOrganizations> wrapper){
        String orgId = TokenUtil.getTokenOrgId();

        IOrgService orgService = SpringUtil.getBean(IOrgService.class);
        GzwProperties gzwProperties = SpringUtil.getBean(GzwProperties.class);
        String gzwOrgId = gzwProperties.getId();
        if (orgId.equals(gzwOrgId)){
            //国资节点
            wrapper.lambda().and(andWrapper ->
                    andWrapper.eq(AuditOrganizations::getStatus, FormStatusConstant.FINISH).or()
                            .eq(AuditOrganizations::getCreateCompanyId, orgId)
            );
        }else{
            List<String> allChildIds = orgService.getAllChildIds(orgId);
            wrapper.lambda().and(andWrapper ->
                    andWrapper.in(AuditOrganizations::getCreateCompanyId, allChildIds)
                            .eq(AuditOrganizations::getStatus, FormStatusConstant.FINISH).or()
                            .eq(AuditOrganizations::getCreateCompanyId, orgId) );
        }

    }
    @Override
    public void download(String key, HttpServletResponse response) {
        if (!fileNameMap.containsKey(key)) {
            log.error("BaseInvestmentPlanServiceImpl 导出excel失败--------> key " + key);
            return;
        }
        String excelName = fileNameMap.get(key);
        String excelPath = environment.getProperty("excel.path") + "/" + key + ".xlsx";
        FileTools.exportExcel(excelPath, excelName, response);
        fileNameMap.remove(key);
    }
}
